package com.morningstar.flow.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.morningstar.flow.antvX6.common.Assign;
import com.morningstar.flow.antvX6.common.CopyTarget;
import com.morningstar.flow.antvX6.node.NodeCopyService;
import com.morningstar.flow.antvX6.node.NodeUserTask;
import com.morningstar.flow.dao.entity.FlowNode;
import com.morningstar.flow.dao.mapper.FlowNodeMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class FlowNodeService extends ServiceImpl<FlowNodeMapper, FlowNode> {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private FlowNodeMapper flowNodeMapper;

    /**
     * 根据流程信息查询流程节点
     *
     * @param processId 流程Id
     * @return 流程节点列表
     */
    public List<FlowNode> selectByProcessId(Long processId) {
        LambdaQueryWrapper<FlowNode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowNode::getProcessId, processId);
        return flowNodeMapper.selectList(wrapper);
    }

    /**
     * 查询流程节点配置信息
     *
     * @param processDefinitionKey 流程定义key
     * @param nodeActivityId       流程【ActivityId】
     * @return 流程节点配置信息
     */
    public FlowNode selectByDefinitionKey(String processDefinitionKey, String nodeActivityId) {
        LambdaQueryWrapper<FlowNode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowNode::getProcessDefineKey, processDefinitionKey);
        wrapper.eq(FlowNode::getNodeActivityId, nodeActivityId);
        return flowNodeMapper.selectOne(wrapper);
    }

    /**
     * 查询流程节点配置信息
     *
     * @param processDefinitionId 流程定义Id
     * @param nodeActivityId      流程 ActivityId
     * @return 流程节点配置信息
     */
    public FlowNode selectByDefinitionId(String processDefinitionId, String nodeActivityId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        return this.selectByDefinitionKey(processDefinition.getKey(), nodeActivityId);
    }

    /**
     * 查询流程节点审批
     *
     * @param processDefinitionKey 流程定义Key
     * @param nodeActivityId       流程 ActivityId
     * @return 审批配置
     */
    public Assign getAssignByDefinitionKey(String processDefinitionKey, String nodeActivityId) {
        FlowNode flowNode = this.selectByDefinitionKey(processDefinitionKey, nodeActivityId);
        return this.getAssign(flowNode);
    }

    /**
     * 查询流程节点审批
     *
     * @param processDefinitionId 流程定义Id
     * @param nodeActivityId      流程 ActivityId
     * @return 审批配置
     */
    public Assign getAssignByDefinitionId(String processDefinitionId, String nodeActivityId) {
        FlowNode flowNode = this.selectByDefinitionId(processDefinitionId, nodeActivityId);
        return this.getAssign(flowNode);
    }

    /**
     * 获取节点审批配置
     *
     * @param flowNode 流程节点信息
     * @return 审批配置
     */
    public Assign getAssign(FlowNode flowNode) {
        if (flowNode.getNodeConfig() == null) {
            throw new RuntimeException("流程节点配置为空");
        }
        NodeUserTask userTask = JSON.parseObject(JSON.toJSONString(flowNode.getNodeConfig()), NodeUserTask.class);
        if (userTask.getData() == null || userTask.getData().getAssign() == null) {
            throw new RuntimeException("流程节点审批配置为空");
        }
        return userTask.getData().getAssign();
    }

    /**
     * 获取抄送节点 抄送人配置
     *
     * @param processDefinitionKey 流程定义Key
     * @param nodeActivityId       流程 ActivityId
     * @return 抄送人配置
     */
    public CopyTarget getCopyTargetByDefinitionKey(String processDefinitionKey, String nodeActivityId) {
        FlowNode flowNode = this.selectByDefinitionKey(processDefinitionKey, nodeActivityId);
        if (flowNode.getNodeConfig() == null) {
            throw new RuntimeException("流程节点配置为空");
        }
        NodeCopyService nodeCopyService = JSON.parseObject(JSON.toJSONString(flowNode.getNodeConfig()), NodeCopyService.class);
        if (nodeCopyService.getData() == null || nodeCopyService.getData().getCopyTarget() == null) {
            throw new RuntimeException("流程节点抄送人配置为空");
        }
        return nodeCopyService.getData().getCopyTarget();
    }

    /**
     * 获取流程结束节点
     *
     * @param processDefinitionId 流程定义KEY
     * @return 流程结束节点
     */
    public FlowNode getEndNodeByDefinitionId(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        return this.getEndNodeByDefinitionKey(processDefinition.getKey());
    }

    /**
     * 获取流程结束节点
     *
     * @param processDefinitionKey 流程定义KEY
     * @return 流程结束节点
     */
    public FlowNode getEndNodeByDefinitionKey(String processDefinitionKey) {
        LambdaQueryWrapper<FlowNode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowNode::getProcessDefineKey, processDefinitionKey);
        wrapper.eq(FlowNode::getNodeType, "node_end");
        return flowNodeMapper.selectOne(wrapper);
    }

    /**
     * 获取流程开始节点
     *
     * @param processDefinitionKey 流程定义KEY
     * @return 流程结束节点
     */
    public FlowNode getStartNodeByDefinitionKey(String processDefinitionKey) {
        LambdaQueryWrapper<FlowNode> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FlowNode::getProcessDefineKey, processDefinitionKey);
        wrapper.eq(FlowNode::getNodeType, "node_start");
        return flowNodeMapper.selectOne(wrapper);
    }
}
